<template>
  <div
    class="on-slider"
    :class="color"
    ref="slider"
    @click="handleContainerClick($event)"
  >
    <div class="icon-wrapper">
      <div class="container">
        <span
          class="icon stop"
          :class="{ passed: isPassed(stop) }"
          v-for="stop of stops"
          :key="stop"
          :style="{
            left: `${
              ((stop - minLeverage) * 100) / (maxLeverage - minLeverage)
            }%`,
          }"
          @click="setValue(stop)"
        >
        </span>
      </div>
    </div>
    <div class="icon-wrapper">
      <div class="container" ref="container">
        <p
          class="display"
          v-for="(stop, index) of stops"
          :key="stop"
          :style="{
            left: `${
              index === 0
                ? '-7px'
                : index === stops.length - 1
                ? 'auto'
                : `${
                    ((stop - minLeverage) * 100) / (maxLeverage - minLeverage)
                  }%`
            }`,
            right: `${index === stops.length - 1 ? `${-7}px` : 'auto'}`,
          }"
          :class="{
            inner: index > 0 && index < stops.length - 1,
            passed: isPassed(stop),
          }"
        >
          {{ stop | clearTailZero }}{{ unit }}
        </p>
      </div>
    </div>
    <div class="slot"></div>
    <div class="bar" :style="{ width: `${width}px` }">
      <span
        class="icon current"
        :class="{ hover: pre !== null }"
        @mousedown="handleMouseDown($event)"
      ></span>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    decimal: {
      // 小数位
      type: Number,
      default: 2,
    },
    value: [Number, String],
    maxLeverage: [Number, String],
    minLeverage: {
      // 最小杠杆数
      type: [Number, String],
      default: "0",
    },
    color: {
      type: String,
      default: "green",
    },
    unit: {
      type: String,
      default: "%",
    },
  },
  data() {
    return {
      start: null,
      pre: null,
      width: 0,
      sliderWidth: null,
      lastVal: 0,
    };
  },
  filters: {
    clearTailZero(number) {
      return `${number}`.replace(/(\.\d*?)(0+)$/, "$1").replace(/\.$/, "");
    },
  },
  computed: {
    maxSlideWidth() {
      if (this.sliderWidth) {
        return this.sliderWidth - 14;
      } else {
        return 0;
      }
    },
    stops() {
      return [this.minLeverage].concat(
        [0.25, 0.5, 0.75, 1.0].map(
          // 基于平均的
          // i => (i * (this.maxLeverage - this.minLeverage) + parseFloat(this.minLeverage)).toFixed(this.decimal)
          // 基于数值非平均
          (i) => (i * this.maxLeverage).toFixed(this.decimal)
        )
      );
    },
  },
  watch: {
    value(val) {
      if (+val === 0) {
        this.width = 0;
      }
    },
    width(val) {
      this.$emit("input", this.calculateValueFromWidth(val));
    },
  },
  methods: {
    isPassed(val) {
      return parseFloat(this.value) >= parseFloat(val);
    },
    calculateValueFromWidth(width) {
      return (
        (width / this.maxSlideWidth) * (this.maxLeverage - this.minLeverage) +
        parseFloat(this.minLeverage)
      ).toFixed(this.decimal);
    },
    handleMouseDown(e) {
      this.start = e.clientX;
      this.pre = this.width;
      document.addEventListener("mousemove", this.handleMouseMove);
      document.addEventListener("mouseup", this.handleMouseUp);
    },
    handleMouseMove(e) {
      let width = this.pre + e.clientX - this.start;
      if (width > this.maxSlideWidth) {
        width = this.maxSlideWidth;
      } else if (width < 0) {
        width = 0;
      }
      this.setValue(this.calculateValueFromWidth(width));
    },
    handleMouseUp(e) {
      this.start = null;
      this.pre = null;
      document.removeEventListener("mousemove", this.handleMouseMove);
      document.removeEventListener("mouseup", this.handleMouseUp);
    },
    init() {
      document.addEventListener("keydown", this.handleKeyDown);
      this.sliderWidth = this.$refs.slider.offsetWidth;
      this.setValue(this.value);
    },
    setValue(value) {
      this.$emit("input", value);
      if (parseFloat(value) === parseFloat(this.minLeverage)) {
        this.width = 0;
      } else {
        this.width =
          ((value - this.minLeverage) / (this.maxLeverage - this.minLeverage)) *
          this.maxSlideWidth;
      }
      this.lastVal = value;
    },
    handleKeyDown(e) {
      const { keyCode } = e;
      if (
        keyCode === 39 &&
        parseFloat(this.value) < parseFloat(this.maxLeverage)
      ) {
        // 右键
        this.setValue(
          (parseFloat(this.value) + 1 / Math.pow(10, this.decimal)).toFixed(
            this.decimal
          )
        );
      } else if (
        keyCode === 37 &&
        parseFloat(this.value) > parseFloat(this.minLeverage)
      ) {
        // 左键
        this.setValue(
          (parseFloat(this.value) - 1 / Math.pow(10, this.decimal)).toFixed(
            this.decimal
          )
        );
      }
    },
    handleContainerClick(e) {
      if (!e.target.matches(".stop")) {
        const left = this.$refs.container.getBoundingClientRect().left;
        let width = e.clientX - left;
        if (width < 0) {
          width = 0;
        } else if (width > this.maxSlideWidth) {
          width = this.maxSlideWidth;
        }
        this.setValue(this.calculateValueFromWidth(width));
      }
    },
  },
  mounted() {
    this.init();
    window.addEventListener("resize", () => {
      this.setValue(this.lastVal);
    });
  },
  beforeDestroy() {
    document.removeEventListener("keydown", this.handleKeyDown);
  },
};
</script>
<style lang="scss" scoped>
$icon-radius: 7px;
$z-index-low: 10;
$z-index-high: 100;

.on-slider {
  position: relative;
  & .icon {
    display: block;
    width: $icon-radius * 2;
    height: $icon-radius * 2;
    border-radius: 50%;
    background: var(--percent-icon-bg);
    cursor: pointer;
    box-sizing: border-box;
    &.current {
      background: var(--color-green);
      transition: all 0.5s;
      position: absolute;
      top: -$icon-radius + 1;
      right: -$icon-radius;
      z-index: $z-index-high;
      color: var(--color);
      &.hover,
      &:hover {
        transform: scale(1.2);
      }
    }
    &.passed {
      background: var(--color-green);
      border-color: var(--color-green);
    }
  }
  & > .icon-wrapper {
    position: relative;
    margin: 0 $icon-radius;
    &:first-child {
      margin-bottom: 5px;
    }
    & + .icon-wrapper {
      & > .container {
        height: 22px;
      }
    }
    & > .container {
      height: $icon-radius * 2;

      font-size: 12px;
      font-family: "Roboto Regular";
      color: var(--color-content);
      user-select: none;
      & > .display,
      & > .icon {
        color: var(--color-des);
        position: absolute;
        z-index: $z-index-low - 1;
        &.passed {
          color: var(--color-green);
        }
      }
      & > .icon {
        margin-left: -$icon-radius;
      }
      & > .inner {
        transform: translateX(-50%);
      }
    }
  }
  & > .slot {
    position: absolute;
    width: 100%;
    height: 2px;
    top: $icon-radius - 1;
    left: 0;
    background: var(--percent-border-bg);
  }
  & > .bar {
    position: absolute;
    height: 2px;
    top: $icon-radius - 1;
    left: $icon-radius;
    background: var(--color-green);
  }
  &.red {
    & .icon {
      &.current {
        background: var(--color-red);
      }
      &.passed {
        background: var(--color-red);
      }
    }
    & > .icon-wrapper {
      & > .container {
        & > .display,
        & > .icon {
          &.passed {
            color: var(--color-red);
          }
        }
      }
    }
    & > .bar {
      background: var(--color-red);
    }
  }
}
</style>
